﻿
//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpNew.h"

#include <QStyle>
#include <QMouseEvent>
#include <QHBoxLayout>
#include "GmTitleBar.h"
#include"GmStyleSheetHelper.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace Sample;

GmTitleBar::GmTitleBar(QWidget *parent, std::wstring objectNamePrefix)
    : QFrame(parent)
    , m_bPressed(false)
{
    setFocusPolicy(Qt::ClickFocus);
    setObjectName("gbmp_title");
    setProperty("is_gbmp_title", true);
    QHBoxLayout* hbox_layout = NEW_AS_QT_CHILD(QHBoxLayout,this);
    hbox_layout->setContentsMargins(0, 0, 0, 0);
    hbox_layout->setSpacing(0);

    m_pIconLabel = NEW_AS_QT_CHILD(QLabel, this);
    m_pIconLabel->setObjectName("gmtitle_icon");
    m_pIconLabel->setVisible(false);
    m_pIconLabel->setMinimumWidth(30);
    m_pIconLabel->setFrameShape(QFrame::NoFrame);
    m_pIconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    m_pIconLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    hbox_layout->addWidget(m_pIconLabel);

    m_pTextLabel = NEW_AS_QT_CHILD(QLabel, this);
    m_pTextLabel->setObjectName("gmtitle_text");
    m_pTextLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    m_pTextLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
    hbox_layout->addWidget(m_pTextLabel);

    QWidget* menuWidget = NEW_AS_QT_CHILD(QWidget, this);
    hbox_layout->addWidget(menuWidget);
    QHBoxLayout* hbox_layout_menu = NEW_AS_QT_LAYOUT(QHBoxLayout);
    hbox_layout_menu->setContentsMargins(0, 0, 0, 0);
    m_pMinButton = new QPushButton;
    std::wstring mminimizeObjectName = objectNamePrefix + L"gmtitle_minimize";
    m_pMinButton->setObjectName(QString::fromStdWString(mminimizeObjectName));
    m_pMinButton->setProperty("is_gbmp_title_mminimize", true);
    m_pMinButton->setToolTip(QString::fromStdWString(L"最小化"));
    m_pMinButton->setDefault(false);
    m_pMinButton->setAutoDefault(true);
    m_pMinButton->setIconSize(QSize(16, 16));
    m_pMinButton->setMinimumWidth(35);
    m_pMinButton->setFlat(true);
    m_pMinButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    m_pMinButton->setIcon(QIcon(QString::fromStdWString(L":/images/最小化面板.png")));
    hbox_layout_menu->addWidget(m_pMinButton);
    connect(m_pMinButton, SIGNAL(clicked()), this, SIGNAL(minimizeRequested()));

    m_pMaxButton = NEW_AS_QT_CHILD(QPushButton, this);
    std::wstring maximizeObjectName = objectNamePrefix + L"gmtitle_maximize";
    m_pMaxButton->setObjectName(QString::fromStdWString(maximizeObjectName));
    m_pMaxButton->setProperty("is_gbmp_title_maximize", true);
    m_pMaxButton->setToolTip(QString::fromStdWString(L"最大化"));
    m_pMaxButton->setDefault(false);
    m_pMaxButton->setIconSize(QSize(16, 16));
    m_pMaxButton->setMinimumWidth(35);
    m_pMaxButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    m_pMaxButton->setIcon(QIcon(QString::fromStdWString(L":/images/最大化面板.png")));
    hbox_layout_menu->addWidget(m_pMaxButton);
    connect(m_pMaxButton, SIGNAL(clicked()), this, SIGNAL(maximizeRequested()));

    m_pRestoreButton = NEW_AS_QT_CHILD(QPushButton, this);
    std::wstring restoreObjectName = objectNamePrefix + L"gmtitle_restore";
    m_pRestoreButton->setObjectName(QString::fromStdWString(restoreObjectName));
    m_pRestoreButton->setProperty("is_gbmp_title_restore", true);
    m_pRestoreButton->setToolTip(QString::fromStdWString(L"还原"));
    m_pRestoreButton->setDefault(false);
    m_pRestoreButton->setIconSize(QSize(16, 16));
    m_pRestoreButton->setMinimumWidth(35);
    m_pRestoreButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    m_pRestoreButton->setIcon(QIcon(QString::fromStdWString(L":/images/还原面板.png")));
    hbox_layout_menu->addWidget(m_pRestoreButton);
    m_pRestoreButton->hide();
    connect(m_pRestoreButton, SIGNAL(clicked()), this, SIGNAL(normalRequested()));

    m_pCloseButton = NEW_AS_QT_CHILD(QPushButton, this);
    std::wstring closeObjectName = objectNamePrefix + L"gmtitle_close";
    m_pCloseButton->setObjectName(QString::fromStdWString(closeObjectName));
    m_pCloseButton->setToolTip(QString::fromStdWString(L"关闭"));
    m_pCloseButton->setDefault(false);
    m_pCloseButton->setIconSize(QSize(16, 16));
    m_pCloseButton->setMinimumWidth(35);
    m_pCloseButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
    m_pCloseButton->setFocusPolicy(Qt::FocusPolicy::NoFocus);
    m_pCloseButton->setVisible(true);
    m_pCloseButton->setProperty("is_gbmp_title_close", true);
    m_pCloseButton->setIcon(QIcon(QString::fromStdWString(L":/images/关闭面板01.png")));
    hbox_layout_menu->addWidget(m_pCloseButton);
    connect(m_pCloseButton, SIGNAL(clicked()), this, SIGNAL(closeRequested()));

    menuWidget->setLayout(hbox_layout_menu);
    menuWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
    setMinimumSize(QSize(100, 31));
    setLayout(hbox_layout);
    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
}

void GmTitleBar::setIconVisible(bool visible)
{
    m_pIconLabel->setVisible(visible);
}

void GmTitleBar::setText(const QString& text)
{
    m_pTextLabel->setText(text);
}

void GmTitleBar::setTextVisible(bool visible)
{
    m_pTextLabel->setVisible(visible);
}

void GmTitleBar::setMinButtonVisible(bool visible)
{
    m_pMinButton->setVisible(visible);
}

void GmTitleBar::setMaxButtonVisible(bool visible)
{
    m_pMaxButton->setVisible(visible);

}

void GmTitleBar::setRestoreButtonVisible(bool visible)
{
    m_pRestoreButton->setVisible(visible);
}

void GmTitleBar::setCloseButtonVisible(bool visible)
{
    m_pCloseButton->setVisible(visible);
}

void GmTitleBar::addWidget(QWidget* widget, int stretch, Qt::Alignment alignment,
    bool at_end)
{
    QHBoxLayout* hbox_layout = qobject_cast<QHBoxLayout*>(layout());
    if (at_end) {
        hbox_layout->insertWidget(hbox_layout->indexOf(m_pTextLabel) + 1,
            widget, stretch, alignment);
    }
    else {
        hbox_layout->insertWidget(0, widget, stretch, alignment);
    }
    widget->setFocusPolicy(Qt::ClickFocus);
}

void GmTitleBar::removeWidget(QWidget* w)
{
    layout()->removeWidget(w);
}

void GmTitleBar::mousePressEvent(QMouseEvent* e)
{
    if (e->button() == Qt::LeftButton) {
        QRect rect = contentsRect();
        rect.adjust(3, 3, -3, 0);
        if (rect.contains(e->pos())) {
            e->accept();
            m_bPressed = true;
            m_pressPos = e->pos();
            m_moveStartPos = e->globalPos();
            return;
        }
    }
    QFrame::mousePressEvent(e);
}

void GmTitleBar::mouseMoveEvent(QMouseEvent* e)
{
    if (!m_bPressed) {
        return QFrame::mouseMoveEvent(e);
    }

    e->accept();
    QPoint cursorPos = e->globalPos();
    QPoint pressed_pos = mapToGlobal(m_pressPos);
    QPoint offset = cursorPos - m_moveStartPos;
    if (offset.x() <= 0) {
        if (cursorPos.x() > pressed_pos.x()) {
            offset.setX(0);
        }
    }
    else {
        if (cursorPos.x() < pressed_pos.x()) {
            offset.setX(0);
        }
    }
    if (offset.y() <= 0) {
        if (cursorPos.y() > pressed_pos.y()) {
            offset.setY(0);
        }
    }
    else {
        if (cursorPos.y() < pressed_pos.y()) {
            offset.setY(0);
        }
    }
    if (offset.x() != 0 || offset.y() != 0) {
        Q_EMIT moveRequested(cursorPos, offset);
    }
    m_moveStartPos = cursorPos;
}

void GmTitleBar::mouseReleaseEvent(QMouseEvent* e)
{
    if (m_bPressed) {
        m_bPressed = false;
        e->accept();
    }
    else {
        QFrame::mouseReleaseEvent(e);
    }
}

bool GmTitleBar::event(QEvent* e)
{
    if (e->type() == QEvent::MouseButtonDblClick) {
        QMouseEvent* mouse_event = static_cast<QMouseEvent*>(e);
        if (mouse_event->button() == Qt::LeftButton) {
            QWidget* parent_widget = childAt(mouse_event->pos());
            if (!parent_widget || !parent_widget->inherits("QAbstractButton")) {
                Q_EMIT maximizeRequested();
                return true;
            }
        }
    }
    return QFrame::event(e);
}

void GmTitleBar::replaceIcons(const std::unordered_map< EButtonType, std::wstring > & iconPathes)
{
    for (const auto & one : iconPathes)
        replaceIcon(one.first, one.second);
}

void GmTitleBar::replaceIcon(const EButtonType buttonType, const std::wstring & iconPath)
{
    switch (buttonType)
    {
    case EButtonType::Minimize:
        m_pMinButton->setIcon(QIcon(QString::fromStdWString(iconPath)));
        break;
    case EButtonType::Maximize:
        m_pMaxButton->setIcon(QIcon(QString::fromStdWString(iconPath)));
        break;
    case EButtonType::Restore:
        m_pRestoreButton->setIcon(QIcon(QString::fromStdWString(iconPath)));
        break;
    case EButtonType::Close:
        m_pCloseButton->setIcon(QIcon(QString::fromStdWString(iconPath)));
        break;
    }
}

